/**
 *    @file       server.cpp
 *
 *    @brief      
 *    @details
 *
 *    @version    1.0
 *    @date       02/10/2014 03:28:36 PM
 *
 *    @author     Theophilus (), wangtf418@gmail.com
 */
#include <sstream>
#include "signals.h"
#include "process.h"
#include "logwrite.h"
#include "toolkit.h"
#include "server.h"
#include "classfactory.h"

//static member
server *server::m_instance = NULL;

//member
server::server()
	: m_classfactory(NULL)
{
	memset(m_threadgroup, 0, sizeof(m_threadgroup));
}

server::~server()
{
	if (m_classfactory)
	{
		delete m_classfactory;
	}
}

bf_int_t server::init()
{
	bf_int_t ret = init_signal();
	if (ret != BF_OK)
	{
		return BF_ERROR;
	}

	ret = init_log();
	if (ret != BF_OK)
	{
		return BF_ERROR;
	}

	ret = m_baseconf.read_conf();
	if (ret != BF_OK)
	{
		return BF_ERROR;
	}

	return BF_OK;
}

bf_int_t server::start()
{
	return BF_OK;
}

bf_int_t server::register_threadgrp(threadgroup *group)
{
	if (!group)
	{
		return BF_ERROR;
	}
	if (group->get_thd_type() >= MAX_THREAD_TYPE)
	{
		return BF_ERROR;
	}
	if (m_threadgroup[group->get_thd_type()])
	{
		return BF_ERROR;
	}
	m_threadgroup[group->get_thd_type()] = group;
	return BF_OK;
}

bf_int_t server::init_signal()
{
	IF_ERR_RETURN(signals::ignore_signal(SIGIO))
	IF_ERR_RETURN(signals::ignore_signal(SIGPIPE))
	IF_ERR_RETURN(signals::ignore_signal(SIGUSR1))
	IF_ERR_RETURN(signals::ignore_signal(SIGUSR2))

	IF_ERR_RETURN(signals::set_sighandler(SIGHUP, sighandler))
	IF_ERR_RETURN(signals::set_sighandler(SIGTERM, sighandler))
	IF_ERR_RETURN(signals::set_sighandler(SIGINT, sighandler))
	IF_ERR_RETURN(signals::set_sighandler(SIGCHLD, sighandler))

	return BF_OK;
}

void server::sighandler(bf_int_t signum)
{
	signals sig;
	switch (signum)
	{
		case SIGINT:
		case SIGTERM:
			{
				sig.clear();
				sig.add(SIGINT);
				sig.add(SIGQUIT);
				sig.add(SIGTERM);
				sig.add(SIGCHLD);
				sig.add(SIGIO);
				sig.add(SIGPIPE);
				sig.add(SIGHUP);
				sig.add(SIGSEGV);
				sig.add_block_signals();
				exit(0);
				break;
			}
		case SIGCHLD:
			{
				process pro;
				pro.waitpid();
				signals::set_sighandler(SIGCHLD, sighandler);
				break;
			}
		default:
			{
				break;
			}
	}
}

bf_int_t server::init_log()
{
	return logwrite::init();
}

void server::process_cycle()
{
	while (true)
	{
		toolkit::usleep_byselect(1, 0);
	}
}

void server::write_messageq_state(bf_int_t logtype)
{
	std::stringstream ss;
	ss.str("");
	ss << "<<server msgqueue len>>:\n";
	for (bf_int_t i = 0; i < MAX_THREAD_TYPE; i ++)	
	{
		if (m_threadgroup[i] == NULL)
		{
			continue;
		}
		ss << "\t<<threadtype:" <<  i << ">>:";
		std::vector<workthread*> &threads = m_threadgroup[i]->get_thread();
		bf_uint32_t threadnum = threads.size();
		for (bf_uint32_t j = 0; j < threadnum; j ++)
		{
			ss << "[" << j << ":" << threads[j]->get_msgq_len() << "]";
		}
		ss << "\n";
	}
	WRITE_LOG(logtype, "%s", ss.str().c_str());
}

